import Axios, { AxiosInstance, AxiosError, AxiosRequestConfig } from 'axios';
import NProgress from '../progress';
// import { message } from '../message';

type Result = {
  Code: number;
};

interface ZnlHttpError extends AxiosError<Result> {
  isCancelRequest?: boolean;
}

const defaultConfig: AxiosRequestConfig = {
  // baseURL
  timeout: 10000,
  headers: {
    Accept: 'application/json, text/plain, */*',
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest',
  },
  // 沿用国际站
  paramsSerializer(params) {
    const processedParams = {};
    for (const key in params) {
      const val = params[key];
      if (val !== null && val !== '') {
        processedParams[key] = val;
      }
    }
    return JSON.stringify(processedParams);
  },
};

/**
 * 仿写国际站请求封装
 * 相比于pure-admin原版: 去除刷新token机制
 */
class ZnlHttp {
  constructor() {
    this.httpInterceptorsRequest();
    this.httpInterceptorsResponse();
  }
  /** 保存当前Axios实例对象 */
  private static axiosInstance: AxiosInstance = Axios.create(defaultConfig);

  public request<T>(method: 'get' | 'post', url: string, param?: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      const config = {
        method,
        url,
        ...param,
      };
      ZnlHttp.axiosInstance
        .request(config)
        .then((response: undefined) => {
          resolve(response);
        })
        .catch(error => {
          reject(error);
        });
    });
  }
  /** 请求拦截 */
  private httpInterceptorsRequest(): void {
    const instance = ZnlHttp.axiosInstance;
    instance.interceptors.response.use(
      config => {
        // 开启进度条动画
        NProgress.start();
        return config;
      },
      (error: ZnlHttpError) => {
        return Promise.reject(error);
      }
    );
  }

  /** 响应拦截 */
  private httpInterceptorsResponse(): void {
    const instance = ZnlHttp.axiosInstance;
    instance.interceptors.response.use(
      response => {
        // 关闭进度条动画
        NProgress.done();
        if (response?.data?.Code === 10001) {
          console.log('重新登录(success)');
        }
        return response.data;
      },
      (error: ZnlHttpError) => {
        if (error.response?.data?.Code === 10001) {
          console.log('重新登录');
        }
        const $error = error;
        $error.isCancelRequest = Axios.isCancel($error);
        // 关闭进度条动画
        NProgress.done();
        // 所有的响应异常 区分来源为取消请求/非取消请求
        return Promise.reject($error);
      }
    );
  }

  /** 单独抽离的post工具函数 */
  public post<T, P>(url: string, params?: AxiosRequestConfig<T>): Promise<P> {
    return this.request<P>('post', url, params);
  }

  /** 单独抽离的get工具函数 */
  public get<T, P>(url: string, params?: AxiosRequestConfig<T>): Promise<P> {
    return this.request<P>('get', url, params);
  }
}

export const http = new ZnlHttp();
